﻿// ———————————————————————–
// <copyright file="ContentProcessingDAL.cs" company="The MITRE Corporation">
//    Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//    http://www.apache.org/licenses/LICENSE-2.0
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.
// </copyright>
// ———————————————————————–
/////////////////////////////////////////////////////////////////////////////////////////////////
// ContentProcessingDAL.cs - 
// Project: "ICNETDAL" - SQL
//
// Language:    C#, .NET 4.0
// Platform:    Windows 7, VS 2010
// Author:      Don McGarry The MITRE Corporation
/////////////////////////////////////////////////////////////////////////////////////////////////

// Copyright (c) 2010 The MITRE Corporation. All rights reserved.
//
// NOTICE
// This software was produced for the U. S. Government
// under Contract No. FA8721-09-C-0001, and is
// subject to the Rights in Noncommercial Computer Software
// and Noncommercial Computer Software Documentation Clause
// (DFARS) 252.227-7014 (JUN 1995)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using ICNETServices;
using System.Text;
using ICNETDAL;
/*
namespace ICNETDAL.SQL
{
  /// <summary>
  /// Contains the methods which pull the data from the database and format it 
  /// </summary>
  public class ContentProcessingDAL : ContentProcessingDALBase
  {
    /// <summary>
    /// Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into a KML feed.
    /// </summary>
    public override string GetAllKML()
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    /// Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into a KML feed.
    /// </summary>
    public override string GetExpiredKML()
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      where p.ExpirationTime <= DateTime.UtcNow
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    /// Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into a KML feed.
    /// </summary>
    public override string GetActiveKML()
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      where p.ExpirationTime > DateTime.UtcNow
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    /// Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into a KML feed.
    /// </summary>
    public override string GetUpdatedKML(DateTime Since)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from p in linqDB.ExposureCaches
                      where p.LastUpdatedTime >= Since.ToUniversalTime()
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    ///  Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into 
    ///  a KML feed with only the information relevant for a specific role.
    /// </summary>
    /// <param name="role">The role that you want to generate a KML feed for.</param>
    /// <param name="roleURI">The URI for the ValueList that contains the role </param>
    public override string GetActiveKMLByRole(string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);

      var exposureCaches = from p2 in linqDB.ExposureCaches
                           where p2.ExpirationTime > DateTime.UtcNow
                           select p2;

      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in exposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    ///  Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into 
    ///  a KML feed with only the information relevant for a specific role.
    /// </summary>
    /// <param name="role">The role that you want to generate a KML feed for.</param>
    /// <param name="roleURI">The URI for the ValueList that contains the role </param>
    public override string GetExpiredKMLByRole(string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var exposureCaches = from p2 in linqDB.ExposureCaches
                           where p2.ExpirationTime <= DateTime.UtcNow
                           select p2;

      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in exposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    ///  Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into 
    ///  a KML feed with only the information relevant for a specific role.
    /// </summary>
    /// <param name="xmlWriter">An XMLWriter that serializes the information from the database</param>
    /// <param name="role">The role that you want to generate a KML feed for.</param>
    /// <param name="roleURI">The URI for the ValueList that contains the role </param>
    public override void GetUpdateKMLByRole(DateTime Since, XmlWriter xmlWriter, string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var exposureCaches = from p2 in linqDB.ExposureCaches
                           where p2.LastUpdatedTime >= Since.ToUniversalTime()
                           select p2;

      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in exposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    ///  Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into 
    ///  a KML feed with only the information relevant for a specific role.
    /// </summary>
    /// <param name="xmlWriter">An XMLWriter that serializes the information from the database</param>
    /// <param name="role">The role that you want to generate a KML feed for.</param>
    /// <param name="roleURI">The URI for the ValueList that contains the role </param>
    public override void GetKMLByRole(XmlWriter xmlWriter, string role, string roleURI)
    {
      EDXLSQLDataContext linqDB = new EDXLSQLDataContext(ICNETSOAConstants.ICNETConnectionString);
      var headlines = from o in linqDB.ExposureCacheRoles
                      where o.ListURI == roleURI && o.Value == role
                      join p in linqDB.ExposureCaches on o.ExposureCacheId equals p.Id
                      orderby p.PublishDate descending
                      select p;

      IList<ExposureCache> dbResults = headlines.ToList<ExposureCache>();
      GetKML(linqDB, dbResults, xmlWriter);
    }

    /// <summary>
    /// Talks to the ICNETSOA database and pulls all of the XML data from the exposure cache, and then formats it into a KML feed.
    /// </summary>
    /// <param name="xmlWriter">An XMLWriter that serializes the information from the database</param>
    private static void GetKML(EDXLSQLDataContext linqDB, IList<ExposureCache> dbResults, XmlWriter xmlWriter)
    {
      HashSet<ICNETStyle> usedStyles = new HashSet<ICNETStyle>();
      XNamespace gml = "http://www.opengis.net/gml";

      foreach (ExposureCache databaseItem in dbResults)
      {
        SelectExposureWhereResult xevar;
        try
        {
          xevar = linqDB.SelectExposureWhere(databaseItem.Id).First();
          if (xevar == null)
          {
            continue;
          }
        }
        catch
        {
          continue;
        }

        if (xevar.Column1 != null && !xevar.Column1.ToString().Contains("<pos />") && !xevar.Column1.ToString().Contains("<geometryMembers />"))
        {
          bool cotItem = false;
          cotItem = databaseItem.Title.Contains("CoT");

          xmlWriter.WriteStartElement("Placemark");

          if (!string.IsNullOrWhiteSpace(databaseItem.Link))
          {
            string[] linkArray = databaseItem.Link.Split('/');

            xmlWriter.WriteAttributeString("Id", linkArray[linkArray.Length - 1]);
          }
          // XWriter.WriteElementString("name", DBItem.Title);
          string title = databaseItem.Title;
          title = title.Replace("(Los Angeles)", string.Empty);
          title = title.Replace("(EDXL-HAVE)", string.Empty);
          title = title.Replace("(EDXL-CAP)", string.Empty);
          title = title.Replace("(CoT)", string.Empty);
          title = title.Replace("  ", " ").Trim();
          title = title.Replace("(EDXL-SitRep)", string.Empty);
          xmlWriter.WriteElementString("name", title);
          xmlWriter.WriteStartElement("description");

          // XWriter.WriteCData(DBItem.Content + "<br/><br/><a href=\"" + DBItem.Link.Replace(ICNETSOAConstants.SyndicationLinkBaseURI, ICNETSOAConstants.ICNETdatalinkURI) + "\">Details</a><br/>");
          string type = databaseItem.Content;
          string styleID = string.Empty;
          string friendlyname = databaseItem.Content;

          if (cotItem)
          {
            ICNETStyle style = KMLStyleEngine.GetStyleFromMatch(MatchTypeEnum.CoT, databaseItem);

            if (style != null)
            {
              usedStyles.AddDependencies(style);
              styleID = @"#" + style.KMLStyleName;

              if (!String.IsNullOrWhiteSpace(style.KMLStyleFriendlyName))
              {
                friendlyname = style.KMLStyleFriendlyName;
              }
            }
            else
            {
              styleID = KMLStyleEngine.DefaultStyleId;
            }

            title = databaseItem.Summary;
          }
          else
          {
            ICNETStyle style = KMLStyleEngine.GetStyleFromMatch(MatchTypeEnum.EDXL, databaseItem);
            usedStyles.AddDependencies(style);
            styleID = @"#" + style.KMLStyleName;
          }

          StringBuilder sbDescription = new StringBuilder(friendlyname + "<br/><br/>" + title + "<br/><br/>");

          bool bEditable = false;
          bool bEditableFound = false;

          //add any extentions
          var ecExt = from o in linqDB.ExposureCacheExtensions
                      where o.ExposureCacheId == databaseItem.Id
                      select o;
          if (ecExt != null)
          {
            IList<ExposureCacheExtension> expCacheListExt = ecExt.ToList<ExposureCacheExtension>();

            foreach (ExposureCacheExtension ext in expCacheListExt)
            {
              string val = ext.Value;

              if (ext.Key.Equals("number"))
              {
                if (ext.Value.Length == 10)
                {
                  val = val.Substring(0, 3) + "-" + val.Substring(3, 3) + "-" + val.Substring(6);
                }
                else if (ext.Value.Length == 11)
                {
                  val = val.Substring(0, 1) + "-" + val.Substring(1, 3) + "-" + val.Substring(4, 3) + "-" + val.Substring(7);
                }
                else if (ext.Value.Length == 7)
                {
                  val = val.Substring(0, 3) + "-" + val.Substring(3);
                }
              }
              else if (ext.Key.Equals("battery"))
              {
                double dVal;
                bool bCanParse;

                bCanParse = Double.TryParse(val, out dVal);
                if (bCanParse)
                {
                  dVal = dVal * 100.0;
                  val = dVal.ToString("##.#") + " %";
                }

              }
              else if (ext.Key.Equals("signal"))
              {
                val = val + " dBm";
              }

              //don't write editable value to details section
              if (ext.Key.Equals("editable"))
              {
                bEditableFound = true;

                bool bVal;
                bool bCanParse;

                bCanParse = Boolean.TryParse(val, out bVal);
                if (bCanParse)
                {
                  bEditable = bVal;
                }
                else
                {
                  bEditableFound = false;
                }
              }
              else
              {
                sbDescription.Append(ext.Key + ": " + val + "<br/>");
              }

            }
          }

          //string sLink = "";
          //sbDescription.Append("<a href=\"" + sLink + "\">Details</a><br/>");
          sbDescription.Append("<a href=\"" + databaseItem.Link + "\">Details</a><br/>");

          xmlWriter.WriteCData(sbDescription.ToString());

          xmlWriter.WriteEndElement();

          if (bEditableFound)
          {
            xmlWriter.WriteStartElement("ExtendedData");
            xmlWriter.WriteAttributeString("xmlns", "icnet", string.Empty, "http://icnet.mitre.org/icall");
            string prefix = xmlWriter.LookupPrefix("http://icnet.mitre.org/icall");
            xmlWriter.WriteElementString(prefix, "editable", "http://icnet.mitre.org/icall", bEditable.ToString());
            xmlWriter.WriteEndElement();
          }

          xmlWriter.WriteElementString("styleUrl", styleID);
          xmlWriter.WriteStartElement("atom", "author", "http://www.w3.org/2005/Atom");
          xmlWriter.WriteElementString("atom", "name", "http://www.w3.org/2005/Atom", databaseItem.Author);
          xmlWriter.WriteEndElement();
          xmlWriter.WriteStartElement("atom", "link", "http://www.w3.org/2005/Atom");
          xmlWriter.WriteAttributeString("href", databaseItem.Link);
          xmlWriter.WriteAttributeString("type", "Text/xml");
          xmlWriter.WriteEndElement();

          if (databaseItem.ExpirationTime.HasValue)
          {
            xmlWriter.WriteStartElement("TimeSpan");
            string endTimeAsString = databaseItem.ExpirationTime.Value.ToString("u");
            endTimeAsString = endTimeAsString.Replace(' ', 'T');
            xmlWriter.WriteElementString("end", endTimeAsString);
            xmlWriter.WriteEndElement();
          }

          if (cotItem)
          {
            xmlWriter.WriteElementString("Snippet", databaseItem.Content);
          }
          else
          {
            xmlWriter.WriteElementString("Snippet", databaseItem.Summary);
          }

          XElement xe = xevar.Column1;
          string valuestr;
          if (xe.DescendantsAndSelf(gml + "Polygon").Count() > 0)
          {
            xmlWriter.WriteStartElement("Polygon");
            xmlWriter.WriteStartElement("outerBoundaryIs");
            xmlWriter.WriteStartElement("LinearRing");
            xmlWriter.WriteStartElement("coordinates");
            valuestr = xe.Descendants(gml + "posList").First().Value;
            int previndex = valuestr.IndexOf(" ");
            int nextindex = valuestr.IndexOf(" ", previndex + 1);
            previndex = 0;
            string temp;
            List<string> sb = new List<string>();
            while (nextindex != -1)
            {
              temp = valuestr.Substring(previndex, nextindex - previndex);
              temp = temp.Replace(" ", ",");
              temp = DEDalUtils.SwapLatLon(temp, false);
              sb.Add(temp);

              // sb.Append(" \reader\n");
              previndex = nextindex + 1;
              nextindex = valuestr.IndexOf(" ", previndex + 1);
              nextindex = valuestr.IndexOf(" ", nextindex + 1);
            }

            temp = valuestr.Substring(previndex);
            temp = temp.Replace(" ", ",");
            temp = DEDalUtils.SwapLatLon(temp, false);
            sb.Add(temp);

            // valuestr = valuestr.Replace(" ", ",");
            for (int i = sb.Count; i != 0; i--)
            {
              xmlWriter.WriteString(sb[i - 1] + " ");
            }

            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();
          }
          else if (xe.DescendantsAndSelf(gml + "Point").Count() > 0)
          {
            xmlWriter.WriteStartElement("Point");
            xmlWriter.WriteStartElement("coordinates");
            valuestr = xe.Descendants(gml + "pos").First().Value;
            valuestr = valuestr.Replace(" ", ",");
            valuestr = DEDalUtils.SwapLatLon(valuestr, false);
            xmlWriter.WriteString(valuestr);
            xmlWriter.WriteEndElement();
            xmlWriter.WriteEndElement();
          }
          else
          {
          }

          xmlWriter.WriteEndElement();
        }
      }

      WriteStyles(usedStyles, xmlWriter);
    }

    /// <summary>
    /// Writes all styles to the XmlWriter in KML format
    /// </summary>
    /// <param name="styles">An enumerable collection of ICNETStyle objects</param>
    /// <param name="xmlWriter">The XmlWriter that will recieve the KML</param>
    public static void WriteStyles(IEnumerable<ICNETStyle> styles, XmlWriter xmlWriter)
    {
      foreach (var style in styles.Where(s => s != null))
      {
        if ((style.Style != null && style.Style.HasAValue()) ||
            (style.StyleMap != null && style.StyleMap.HasAValue()))
        {
          style.WriteXml(xmlWriter);
        }
      }
    }
  }

  /// <summary>
  /// Just stick this here until we figure out what to do with it
  /// </summary>
  public static class tempExtensionClass
  {
    /// <summary>
    /// Adds the included style and its dependencies to the list of used styles. This ensures that 
    /// StyleMaps have all of their states included in the output XML,
    /// </summary>
    /// <param name="styles">The collection of currently used styles</param>
    /// <param name="style">The style to add and whose dependencies need to be checked</param>
    public static void AddDependencies(this HashSet<ICNETStyle> styles, ICNETStyle style)
    {
      styles.Add(style);
      if (style.StyleMap != null)
      {
        foreach (string depId in style.StyleMap.StyleDependencies)
        {
          styles.Add(KMLStyleEngine.GetStyleFromId(depId));
        }
      }
    }
  }
}

*/